package main;

import input.CalendarDataProvider;
import input.GoogleAPIDataProvider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import calendar.Calendar;
import calendar.Event;
import output.N3FileParser;
import output.POSLFileParser;
import output.Parser;
import output.DebugWriter;
import java.util.List;
import java.util.ArrayList;

/**
 * Servlet implementation class 
 */
public class Main extends HttpServlet {
	
	private List<Parser> parsers;
	private CalendarDataProvider calendarDataProvider;

	private static String rootDirectory;
	private static String rootDirectory_out;	
	
	public Main() {
		parsers = new ArrayList<Parser>();
		calendarDataProvider = new GoogleAPIDataProvider();		
	}
	
	private static final long serialVersionUID = 1L;
      
	public void init() throws ServletException {
		super.init();

	//	rootDirectory=getServletContext().getRealPath("/") + File.separator + "profileFiles" + File.separator;
	//	rootDirectory_out=getServletContext().getRealPath("/") + File.separator + "profileFilesOut" + File.separator;
	}
	
	protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();		
		out.println("<html><body><h2>Google Calendar Servlet Project - results</h2>");
		
		//fetch parameters from index.jsp page
		String inputFolderPath = request.getParameter("inputpath").toString();
		String outputFolderPath = request.getParameter("outputpath").toString();
		
		if ("".equals(inputFolderPath)||("".equals(outputFolderPath))){
			
			out.println("You must enter input and output folders.");
			
		}else{
			
			rootDirectory=inputFolderPath + File.separator;
			rootDirectory_out=outputFolderPath + File.separator;		
			
			
			out.println("<h3>Event taxonomy:</h3>"+GoogleAPIDataProvider.getEventTaxonomy());
			out.println("<h3>Input directory:</h3>"+rootDirectory);
			out.println("<h3>Ouput directory:</h3>"+rootDirectory_out);
			out.print("<h3>The files processed:</h3>");
			
			parsers.add(new N3FileParser());
			parsers.add(new POSLFileParser());
			
			StringWriter debugInfo = new StringWriter();		
			
			//1. processFiles
			processFiles(parsers, new DebugWriter(debugInfo));		
			
			//2. displayResults
			out.println(debugInfo.toString());
		}
		
		out.print("</body></html>");
		
	}

	/**
	 * For each parser looks for all filenames in inputDirectory matching the
	 * filename of a parser, and updates their calendar data. 
	 * It also writes logging information to debugInfoWriter.
	 * @param parsers
	 * @param debugInfoWriter
	 * @throws FileNotFoundException 
	 */
	private void processFiles(List<Parser> parsers, DebugWriter debugInfoWriter) throws FileNotFoundException {
		
		debugInfoWriter.write("<ol>");
		
		//for each parser find all files matching it
		for (Parser parser : parsers){
			
			//for each file replace old calendar with new calendar
			for (String filename : findFilenames(parser.getFilenamePattern())){
				
				/*
				 * The idea: 
				 * - for each file:
				 * 1. get the url from the file
				 * 2. get the data from url
				 * 3. insert the data back to the file, replacing the old data
				 * 4. log the results
				 */
				
				//1. get the url from the file
				System.out.println("Getting calendar url from file '"+rootDirectory+filename+"'");				
				String calUrl = parser.getUserCalUrlFromFile(rootDirectory+filename);
				if (calUrl==null){
					System.err.println("Calendar data missing for file "+filename+". File skipped.");
					continue;
				}
				
				//2. get the data from url
				System.out.println("Url='"+calUrl+"'\nGetting calendar data from the calendar url");				
				Calendar calendar = calendarDataProvider.getCalendarData(calUrl);				
				System.out.println(calendar.getEvents().size()+" events received");
				
				//3. insert the data back to the file, replacing the old data
				System.out.println("Writing the events to output file '"+rootDirectory_out+filename+"'");				
				parser.writeCalendarData(rootDirectory+filename, calendar, rootDirectory_out+filename);
				
				System.out.println("ok\n");
				
				//4. log the results
				debugInfoWriter.writeln("<li>"+"<b>"+filename+"</b>");
				debugInfoWriter.writeln("<b>Calendar url:</b> <a href=\""+calUrl+"\">"+calUrl+"</a>");
				debugInfoWriter.writeln("<b>Calendar ID: </b>"+calendar.getCalendarID()+"");
				debugInfoWriter.write("<b>Events:</b>");
				debugInfoWriter.write("<ul>");				
				for (Event e : calendar.getEvents()){					
					debugInfoWriter.writeln("<li>"+e.getEventTitle()+": "+e.getStartTime().toString()+" - "+e.getEndTime().toString()+"</li>");					
				}
				debugInfoWriter.writeln("</ul></li>");												
			}								
		}
		debugInfoWriter.writeln("</ol>");
				
	}

	/**
	 * Returns a list of filenames in inputDirectory matching the filenamePattern.
	 * @param filenamePattern
	 * @return
	 * @throws FileNotFoundException 
	 */
	private List<String> findFilenames(String filenamePattern) throws FileNotFoundException {
		/*try {
			File rootDir = new File(getServletContext().getResource(rootDirectory).getFile());			
			return findFilenames(filenamePattern,rootDir);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}	
		return null;*/				

		File rootDir = new File(rootDirectory);						
		return findFilenames(filenamePattern,rootDir);
	}

	/**
	 * eturns a list of filenames in rootDir matching the filenamePattern (recursive function).
	 * @param filenamePattern
	 * @param rootDir
	 * @return
	 * @throws FileNotFoundException 
	 */
	private List<String> findFilenames(String filenamePattern, File rootDir) throws FileNotFoundException {				
		String[] files = rootDir.list();
		
		//if the directory is hard coded, the user will have to copy it to proper place if not existing
		if (files==null){
			throw new FileNotFoundException(rootDir.toString());			
		}
		
		List<String> resultList = new ArrayList<String>();
		for (String filename : files){
			File file = new File(filename);			
			if (file.isDirectory()){
				resultList.addAll(findFilenames(filenamePattern,file));
			}else{
				if (filename.matches(filenamePattern)){					
					resultList.add(filename);
				}
			}
		}
		return resultList;
	}

	public void destroy() {
		super.destroy();
	}

	/**
	 * This is just additional method, which allows to run the application as
	 * Java application instead of a servlet.
	 * @param args
	 * @throws ServletException
	 * @throws IOException
	 */
	public static void main(String[] args) throws ServletException, IOException{
		Main main = new Main();

		//HERE ARE THE PATHS FOR THE JAVA APPLCIATION
		rootDirectory="./profileFiles/";
		rootDirectory_out="./profileFilesOut/";
		
		main.parsers.add(new N3FileParser());
		main.parsers.add(new POSLFileParser());
		
		StringWriter debugInfo = new StringWriter();		
		
		main.processFiles(main.parsers, new DebugWriter(debugInfo));		
		
		System.out.println(debugInfo.toString());	
	}

}

